package bai.tool.util;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.interfaces.Compare;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class QueryUtil {

    /**
     * 构造qw查询条件
     *
     * @param searchObj    DO
     * @param parameterMap 查询参数
     * @return
     */
    public static <T> QueryWrapper<T> initQueryWrapper(Class<T> targetClass, Map<String, Object> parameterMap) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isEmpty(parameterMap)) {
            return queryWrapper;
        }

        parameterMap.forEach((key, value) -> {
            String[] parts = key.split("__");
            String field;
            String rule;

            if (parts.length == 1) {
                // 默认EQ条件
                field = parts[0];
                rule = QueryRuleEnum.EQ.getCondition();
            } else if (parts.length >= 2) {
                // 分解字段名和条件
                field = parts[0];
                rule = parts[1];
            } else {
                log.warn("Invalid parameter key format: {}", key);
                return;
            }

            // 转换查询规则
            QueryRuleEnum ruleEnum = QueryRuleEnum.getByValue(rule);
            if (ruleEnum == null) {
                log.warn("Unsupported query rule: {}", rule);
                return;
            }

            // 值处理
            Object processedValue = processValue(ruleEnum, value);
            if (processedValue == null) {
                log.warn("Empty value for field: {}", field);
                return;
            }

            // 应用查询条件
            try {
                ruleEnum.getCriteria().apply(queryWrapper, field, processedValue);
            } catch (Exception e) {
                log.error("Apply query condition error, field: {}, rule: {}, value: {}",
                        field, rule, processedValue, e);
            }
        });

        return queryWrapper;
    }

    private static Object processValue(QueryRuleEnum rule, Object value) {
        if (value == null) return null;

        // 特殊规则处理
        switch (rule) {
            case IN:
                if (value instanceof String) {
                    return ((String) value).split("\\s*,\\s*");
                } else if (value instanceof Iterable) {
                    List<Object> list = new ArrayList<>();
                    ((Iterable<?>) value).forEach(list::add);
                    return list.toArray();
                }
                return value;

            case LIKE:
                return "%" + value + "%";
            case LEFT_LIKE:
                return "%" + value;
            case RIGHT_LIKE:
                return value + "%";

            case SQL_RULES:
                return value.toString();

            default:
                return value;
        }
    }
}

/**
 * 匹配规则
 */
@Getter
@AllArgsConstructor
enum QueryRuleEnum {
    GT(">" , "gt" , "大于" , Compare::gt),
    GE(">=" , "ge" , "大于等于" , Compare::ge),
    LT("<" , "lt" , "小于" , Compare::lt),
    LE("<=" , "le" , "小于等于" , Compare::le),
    EQ("=" , "eq" , "等于" , Compare::eq),
    NE("!=" , "ne" , "不等于" , Compare::ne),
    IN("IN" , "in" , "包含" , (queryWrapper, name, value) -> queryWrapper.in(name, (Object[]) value)),
    LIKE("LIKE" , "like" , "全模糊" , Compare::like),
    LEFT_LIKE("LEFT_LIKE" , "left_like" , "左模糊" , Compare::likeLeft),
    RIGHT_LIKE("RIGHT_LIKE" , "right_like" , "右模糊" , Compare::likeRight),
    SQL_RULES("USE_SQL_RULES" , "ext" , "自定义SQL片段" , (queryWrapper, name, value) -> queryWrapper.apply((String) value));

    final private String value;
    final private String condition;
    final private String msg;
    final private TConsumer criteria;

    public static QueryRuleEnum getByValue(String value) {
        if (ObjectUtil.isEmpty(value)) {
            return null;
        }
        for (QueryRuleEnum rule : QueryRuleEnum.values()) {
            if (rule.getValue().equals(value)) {
                return rule;
            }
        }
        return null;
    }
}

/**
 * 切片函数
 */
@FunctionalInterface
interface TConsumer {
    void apply(QueryWrapper<?> queryWrapper, String name, Object value);
}

/**
 * 参数
 */
@Data
class QueryRuleVO {
    private String field;
    private String rule;
    private String val;
}